package com.example.midprojcampusspringboot.controller;

import com.example.midprojcampusspringboot.common.ResultUtil;
import com.example.midprojcampusspringboot.domain.entity.User;
import com.example.midprojcampusspringboot.domain.params.UserAddParams;
import com.example.midprojcampusspringboot.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * 用户管理
 *
 * @Author Fengwei
 * @Description
 * a)用户登录：登录成功，获得请求Token.
 * b)新增用户
 * c)用户查询：按照名字或id查询。
 *
 **/
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 用户注册
     * @param user
     * @return
     */
    @PostMapping("/register")
    public ResponseEntity<String> register(User user) {
        // 参数判断省略
        // ...

        try {
            userService.register(user);
            return ResponseEntity.ok().build();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 错误提示信息省略...
        return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body("客户端传参错误");
    }

    /**
     * 1.用户登录（身份认证）
     * Shiro会缓存认证信息
     *
     * @param username
     * @param password
     * @return
     */
    @PostMapping("/login")
    public ResponseEntity<String> login(String username, String password) {
        // 前期的注入工作已经由SpringBoot完成了
        // 获取当前来访用户的主体对象
        Subject subject = SecurityUtils.getSubject();

        try {
            // 执行登录，如果登录失败会直接抛出异常，并进入对应的catch
            subject.login(new UsernamePasswordToken(username, password));

            // 获取主体的身份信息
            // 实际上是User。为什么？
            // 取决于LoginRealm中的doGetAuthenticationInfo()方法中SimpleAuthenticationInfo构造函数的第一个参数
            User user = (User) subject.getPrincipal();

            // 生成jwt
            String jwt = userService.generateJwt(user.getLoginName());

            // 将jwt放入到响应头中
            return ResponseEntity.ok().header("token", jwt).build();

        } catch (UnknownAccountException e) {
            // username 错误
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("username不存在");
        } catch (IncorrectCredentialsException e) {
            // password 错误
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("password错误");
        }
    }

    /**
     * 2.新增用户
     *
     **/
    @PostMapping("/create")
    public ResultUtil addTeacher(@RequestBody @Validated UserAddParams params) {
        User user = new User();
        BeanUtils.copyProperties(params, user);
        return userService.save(user) ? ResultUtil.success("添加成功") : ResultUtil.error("添加失败");
    }

    /**
     * 3.用户查询：按照名字或id查询。
     *
     **/
    @GetMapping("/users")
    public ResultUtil getUser(@RequestParam(required = false) Long id, @RequestParam(required = false) String loginName) {
        return ResultUtil.success(userService.getUserByIdOrLoginName(id,loginName));
    }
}
